// 出处： https://www.bilibili.com/read/cv22740260/?from=search&spm_id_from=333.337.0.0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hs/hs.h>

#define PATTERN_COUNT 1000

// 字符串复制
char *strdup(const char *str)
{
    int n = strlen(str) + 1;
    char *dup = malloc(n);
    if(dup)
    {
        strcpy(dup, str);
    }
    return dup;
}

// 回调函数
int eventHandler(unsigned int id, unsigned long long from, unsigned long long to,
        unsigned int flags, void *ctx)
{
    printf("Match found at end offset %llu, pattern %u\n", to, id);
    return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <file>\n", argv[0]);
        return 1;
    }

    // 含有正则表达式的文件
    const char *pattern_file = argv[1];

    // 打开正则表达式文件
    FILE *fp = fopen(pattern_file, "r");
    if (fp == NULL) {
        fprintf(stderr, "Error opening pattern file\n");
        return 1;
    }

    // 逐条读入正则表达式，写入数组
    char **patterns = malloc(PATTERN_COUNT * sizeof(char *));
    if (patterns == NULL) {
        fprintf(stderr, "Error allocating pattern array\n");
        fclose(fp);
        return 1;
    }
    unsigned int ids[PATTERN_COUNT] = {-1};

    char buffer[1024];
    int i = 0;
    while (fgets(buffer, sizeof(buffer), fp) != NULL && i < PATTERN_COUNT) {
        // 删除多余的'\n'
        size_t len = strlen(buffer);
        if (buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        }
        // 复制到数组中
        patterns[i] = strdup(buffer);
        ids[i] = 100 + i;
        if (patterns[i] == NULL) {
            fprintf(stderr, "Error allocating pattern\n");
            fclose(fp);
            return 1;
        }
        i++;
    }
    fclose(fp);

    // 编译正则表达式
    hs_database_t *database = NULL;
    hs_compile_error_t *compile_err = NULL;
    hs_error_t err = hs_compile_multi((const char * const*)patterns,
                                       NULL, ids, i,
                                       HS_MODE_BLOCK,
                                       NULL, &database, &compile_err);
    if (err != HS_SUCCESS) {
        fprintf(stderr, "Error compiling patterns: %s\n", compile_err->message);
        hs_free_compile_error(compile_err);
        for (int j = 0; j < i; j++) {
            free(patterns[j]);
        }
        free(patterns);
        return 1;
    }

    // 分配临时空间(指针必须初始化为NULL)
    hs_scratch_t *scratch = NULL;
    err = hs_alloc_scratch(database, &scratch);
    if (err != HS_SUCCESS) {
        fprintf(stderr, "Error allocating scratch space\n");
        hs_free_database(database);
        for (int j = 0; j < i; j++) {
            free(patterns[j]);
        }
        free(patterns);
        return 1;
    }

    // 匹配字符串
    const char *str = "23456#SSSSS";

    // 单模+块匹配
    err = hs_scan(database, str, strlen(str), 0, scratch, eventHandler, NULL);
    if (err != HS_SUCCESS) {
        fprintf(stderr, "Error scanning string\n");
        hs_free_scratch(scratch);
        hs_free_database(database);
        for (int j = 0; j < i; j++) {
            free(patterns[j]);
        }
        free(patterns);
        return 1;
    }

    // 释放空间
    hs_free_scratch(scratch);
    hs_free_database(database);
    for (int j = 0; j < i; j++) {
        free(patterns[j]);
    }
    free(patterns);

    return 0;
}
